mod handlers;
mod routes;

use axum::{
    http::{
        header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE},
        HeaderValue, Method,
    },
    Router,
};
use fluviox_shared::{Config, database::Database, FluvioManager};
use std::sync::Arc;
use tower::ServiceBuilder;
use tower_http::{
    cors::CorsLayer,
    trace::TraceLayer,
};
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};

pub struct AppState {
    pub db: Database,
    pub config: Config,
    pub fluvio: FluvioManager,
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // 初始化日志
    tracing_subscriber::registry()
        .with(
            tracing_subscriber::EnvFilter::try_from_default_env()
                .unwrap_or_else(|_| "fluviox_api_gateway=debug,tower_http=debug".into()),
        )
        .with(tracing_subscriber::fmt::layer())
        .init();

    // 加载配置
    let config = Config::from_env()?;
    tracing::info!("配置加载完成: {:?}", config);

    // 初始化数据库
    let db = Database::new(&config.database.url).await?;
    tracing::info!("数据库连接成功");

    // 初始化Fluvio管理器
    let fluvio = FluvioManager::new(&config.fluvio.cluster_endpoint).await?;
    tracing::info!("Fluvio连接成功");

    // 初始化默认主题
    fluvio.initialize_default_topics().await?;
    tracing::info!("默认主题初始化完成");

    // 创建应用状态
    let state = Arc::new(AppState { db, config: config.clone(), fluvio });

    // 配置CORS
    let cors = CorsLayer::new()
        .allow_origin(
            config.server.cors_origins
                .iter()
                .map(|origin| origin.parse::<HeaderValue>().unwrap())
                .collect::<Vec<_>>(),
        )
        .allow_methods([Method::GET, Method::POST, Method::PUT, Method::DELETE])
        .allow_headers([AUTHORIZATION, ACCEPT, CONTENT_TYPE]);

    // 构建路由
    let app = Router::new()
        .nest("/api/v1", routes::create_routes())
        .layer(
            ServiceBuilder::new()
                .layer(TraceLayer::new_for_http())
                .layer(cors),
        )
        .with_state(state);

    // 启动服务器
    let listener = tokio::net::TcpListener::bind(format!("{}:{}", config.server.host, config.server.port)).await?;
    tracing::info!("服务器启动在 http://{}:{}", config.server.host, config.server.port);

    axum::serve(listener, app).await?;

    Ok(())
}
